package auth

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
)

// AuthorizationCode authorization code 认证过程，callback是webview或者浏览器授权后回调接口，传入授权后的code。
// grant_type authorization code的认证过程如下：
// 1. 引导用户到网站授权，浏览器页面输入对应的授权地址。其中默认回调url中会带上code参数。
// 2. 获取code
// 3. POST到指定的URI获取Token。
type AuthorizationCode interface {
	// CallAuth 生成一个用户授权地址。
	CallAuth() string
	// Callback 回调函数。
	Callback(code string) (Token, error)
	// RefreshToken 刷新token，重新获取。
	RefreshToken() (Token, error)
}

// Token AuthorizationCode 认证后的结构体。
type Token struct {
	AccessToken  string `json:"access_token" map:"access_token"`
	TokenType    string `json:"token_type" map:"token_type"`
	ExpiresIn    int64  `json:"expires_in" map:"expires_in"`
	RefreshToken string `json:"refresh_token" map:"refresh_token"`
	Scope        string `json:"scope" map:"scope"`
	CreatedAt    int64  `json:"created_at" map:"created_at"`
}

// CallBack 发送post请求。
func CallBack(uri, clientID, secret, code, redirectUrl, grantType string) (Token, error) {
	var token = Token{}
	res, err := http.PostForm(
		uri,
		url.Values{
			"client_id":     {clientID},
			"client_secret": {secret},
			"code":          {code},
			"redirect_uri":  {redirectUrl},
			"grant_type":    {grantType},
		},
	)
	if err != nil {
		return token, err
	}

	all, err := ioutil.ReadAll(res.Body)

	if err != nil {
		return token, err
	}

	if res.StatusCode != 200 {
		fmt.Println(errors.New(string(all)))
	}
	if err = json.Unmarshal(all, &token); err != nil {
		return token, err
	}

	return token, nil
}

// RefreshToken token过期后重新获取token。
func RefreshToken(uri, refreshToken string) (token Token, err error) {
	res, err := http.PostForm(
		uri,
		url.Values{
			"refresh_token": {refreshToken},
			"grant_type":    {"refresh_token"},
		},
	)

	if err != nil {
		return
	}
	all, err := ioutil.ReadAll(res.Body)

	if err != nil {
		return
	}
	err = json.Unmarshal(all, &token)

	if err != nil {
		return
	}
	return
}
